# -*-coding:utf-8-*-
import numpy as np
import matplotlib.pyplot as plt
import cv2

plt.rcParams['font.family'] = 'DejaVu Sans'

img = cv2.imread('laugh.jpg', cv2.IMREAD_GRAYSCALE)

# 显示图像
plt.imshow(img, cmap='gray')
plt.show()

# 计算直方图
hist, bins = np.histogram(img.ravel(), bins=256, range=[0, 256])

# 绘制直方图
plt.bar(bins[:-1], hist, width=1)
plt.show()

# 添加椒盐噪声
noise = np.zeros(img.shape, np.uint8)
cv2.randu(noise, 0, 256)
salt = noise > 250
pepper = noise < 6
img_salt_pepper = img.copy()
img_salt_pepper[salt] = 255
img_salt_pepper[pepper] = 0

# 添加高斯噪声
mean = 0
var = 100
sigma = var ** 0.5
gaussian = np.random.normal(mean, sigma, img.shape)
img_gaussian = img.astype(np.float32) + gaussian
img_gaussian = np.clip(img_gaussian, 0, 255).astype(np.uint8)

# 计算信噪比
snr_salt_pepper = 10 * np.log10(np.mean(img) / np.var(img_salt_pepper - img))
snr_gaussian = 10 * np.log10(np.mean(img) / np.var(img_gaussian - img))
print('SNR (salt and pepper):', snr_salt_pepper)
print('SNR (Gaussian):', snr_gaussian)

# 边缘检测
edges = cv2.Canny(img, 100, 200)
edges_salt_pepper = cv2.Canny(img_salt_pepper, 100, 200)
edges_gaussian = cv2.Canny(img_gaussian, 100, 200)

# 显示边缘特征图
plt.subplot(131), plt.imshow(edges, cmap='gray')
plt.title('原始图像'), plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(edges_salt_pepper, cmap='gray')
plt.title('加入椒盐噪声'), plt.xticks([]), plt.yticks([])
plt.subplot(133), plt.imshow(edges_gaussian, cmap='gray')
plt.title('加入高斯噪声'), plt.xticks([]), plt.yticks([])
plt.show()

# 二值化处理
_, binary = cv2.threshold(edges, 0, 255, cv2.THRESH_BINARY)
_, binary_salt_pepper = cv2.threshold(edges_salt_pepper, 0, 255, cv2.THRESH_BINARY)
_, binary_gaussian = cv2.threshold(edges_gaussian, 0, 255, cv2.THRESH_BINARY)

# 计算边缘比例
edge_ratio = np.sum(binary) / img.size
edge_ratio_salt_pepper = np.sum(binary_salt_pepper) / img.size
edge_ratio_gaussian = np.sum(binary_gaussian) / img.size
print('边缘比例:', edge_ratio)
print('边缘比例 (加入椒盐噪声):', edge_ratio_salt_pepper)
print('边缘比例 (加入高斯噪声):', edge_ratio_gaussian)